﻿Imports System.IO
Imports System.Text.Encoding

''' <summary>
''' 文件元数据。
''' 可以使用以下几种构造方法：
''' 本地路径：new FileItem("C:/temp.jpg");
''' 本地文件：new FileItem(new FileInfo("C:/temp.jpg"));
''' 字节流：new FileItem("abc.jpg", bytes);
''' </summary>
Public Class FileItem
    Private fileName As String
    Private mimeType As String
    Private content As Byte()
    Private fileInfo As FileInfo

    ''' <summary>
    ''' 基于本地文件的构造器。
    ''' </summary>
    ''' <param name="fileInfo">本地文件</param>
    Public Sub New(ByVal fileInfo As FileInfo)
        If fileInfo Is Nothing OrElse Not fileInfo.Exists Then
            Throw New ArgumentException("fileInfo is null or not exists!")
        End If
        Me.fileInfo = fileInfo
    End Sub

    ''' <summary>
    ''' 基于本地文件全路径的构造器。
    ''' </summary>
    ''' <param name="filePath">本地文件全路径</param>
    Public Sub New(ByVal filePath As String)
        Me.New(New FileInfo(filePath))
    End Sub

    ''' <summary>
    ''' 基于文件名和字节流的构造器。
    ''' </summary>
    ''' <param name="fileName">文件名称（服务端持久化字节流到磁盘时的文件名）</param>
    ''' <param name="content">文件字节流</param>
    Public Sub New(ByVal fileName As String, ByVal content As Byte())
        If String.IsNullOrEmpty(fileName) Then
            Throw New ArgumentNullException("fileName")
        End If
        If content Is Nothing OrElse content.Length = 0 Then
            Throw New ArgumentNullException("content")
        End If

        Me.fileName = fileName
        Me.content = content
    End Sub

    ''' <summary>
    ''' 基于文件名、字节流和媒体类型的构造器。
    ''' </summary>
    ''' <param name="fileName">文件名（服务端持久化字节流到磁盘时的文件名）</param>
    ''' <param name="content">文件字节流</param>
    ''' <param name="mimeType">媒体类型</param>
    Public Sub New(ByVal fileName As String, ByVal content As Byte(), ByVal mimeType As String)
        Me.New(fileName, content)
        If String.IsNullOrEmpty(mimeType) Then
            Throw New ArgumentNullException("mimeType")
        End If
        Me.mimeType = mimeType
    End Sub

#Region "GetFileExtension"

    ''' <summary>
    ''' 获取文件的真实媒体类型。目前只支持JPG, GIF, PNG, BMP四种图片文件。
    ''' </summary>
    ''' <param name="fileData">文件字节流</param>
    ''' <returns>媒体类型</returns>
    Public Shared Function GetMimeType(ByVal fileData As Byte()) As String
        Dim suffix As String = GetFileSuffix(fileData)
        Dim mimeType As String

        Select Case suffix
            Case "JPG"
                mimeType = "image/jpeg"
                Exit Select
            Case "GIF"
                mimeType = "image/gif"
                Exit Select
            Case "PNG"
                mimeType = "image/png"
                Exit Select
            Case "BMP"
                mimeType = "image/bmp"
                Exit Select
            Case Else
                mimeType = "application/octet-stream"
                Exit Select
        End Select

        Return mimeType
    End Function

    ''' <summary>
    ''' 获取文件的真实后缀名。目前只支持JPG, GIF, PNG, BMP四种图片文件。
    ''' </summary>
    ''' <param name="fileData">文件字节流</param>
    ''' <returns>JPG, GIF, PNG or null</returns>
    Public Shared Function GetFileSuffix(ByVal fileData As Byte()) As String
        If fileData Is Nothing OrElse fileData.Length < 10 Then
            Return Nothing
        End If
        If [Default].GetChars(fileData, 0, 3) = "GIF" Then
            Return "GIF"
        ElseIf [Default].GetChars(fileData, 1, 3) = "PNG" Then
            Return "PNG"
        ElseIf [Default].GetChars(fileData, 6, 4) = "JFIF" Then
            Return "JPG"

        ElseIf [Default].GetChars(fileData, 0, 2) = "BM" Then
            Return "BMP"
        Else
            Return Nothing
        End If
    End Function

#End Region

    Public Function GetFileName() As String
        If Me.fileName Is Nothing AndAlso Me.fileInfo IsNot Nothing AndAlso Me.fileInfo.Exists Then
            Me.fileName = Me.fileInfo.FullName
        End If
        Return Me.fileName
    End Function

    Public Function GetMimeType() As String
        If Me.mimeType Is Nothing Then
            'Me.mimeType = TopUtils.GetMimeType(GetContent())
        End If
        Return Me.mimeType
    End Function

    Public Function GetContent() As Byte()
        If Me.content Is Nothing AndAlso Me.fileInfo IsNot Nothing AndAlso Me.fileInfo.Exists Then
            Using fileStream As System.IO.Stream = Me.fileInfo.OpenRead()
                Me.content = New Byte(fileStream.Length - 1) {}
                fileStream.Read(content, 0, content.Length)
            End Using
        End If

        Return Me.content
    End Function

End Class